/*
本模块提供查询进程信息及系统信息的工具。
所有信息均来自于"/proc"文件系统。
*/

#ifndef PROC_H
#define PROC_H

#include <stdint.h>
#include <string>
#include <set>
#include <list>
#include <ostream>
#include <sched.h>

#include "system.h"
#include "utils.h"

namespace ProcFsUtils
{

/*获取一个表示proc文件系统中相应进程下的某个文件的完整路径
 *例如对于：pid = 100, file = "stat"， 
 *返回值为"/proc/100/stat"*/
std::string getProcFilePath(pid_t pid, const char *file);

/*获取proc文件系统中某进程下某文件的内容
 *例如对于：pid = 100, file = "stat"， 
 *返回值为"/proc/100/stat"这个文件的内容*/
std::string getProcFileContent(pid_t pid, const char *file);

/*获取系统中所有进程的PID，
 *把所有PID值保存在all_pid中，
 *该函数会清空all_pid中原有的内容*/
void getAllPid(std::set<pid_t> *all_pid);

}


/*    保存"/proc/N/status"文件中的内容，以字符串形式保存每一个属性的内容。
 *文件中的每一行对应一个字段，字段名为一行中冒号左侧（去掉两侧空白）的部分，
 *字段内容为一行中冒号右侧（去掉两侧空白）的内容。
 *
 *    不对属性内容做任何解释，所有属性值都保存为字符串格式，仅去掉两侧空白字符。
 *    把文件提供的所有信息都一对一原样保存到结构体中，不做任何筛选和解析。
 *本结构体的意义在于提供一个针对该文件的读取文件内容的简化手段,
 *使得上层代码可以面对一个干净整齐的结构体而不是一列字符，
 *免去文件操作的繁琐细节。*/
struct TaskStatusFileContent
{
    std::string Name;
    std::string State;
    std::string Tgid;
    std::string Ngid;
    std::string Pid;
    std::string PPid;
    std::string TracerPid;
    std::string Uid;
    std::string Gid;
    std::string FDSize;
    std::string Groups;
    std::string VmPeak;
    std::string VmSize;
    std::string VmLck;
    std::string VmPin;
    std::string VmHWM;
    std::string VmRSS;
    std::string VmData;
    std::string VmStk;
    std::string VmExe;
    std::string VmLib;
    std::string VmPTE;
    std::string VmSwap;
    std::string Threads;
    std::string SigQ;
    std::string SigPnd;
    std::string ShdPnd;
    std::string SigBlk;
    std::string SigIgn;
    std::string SigCgt;
    std::string CapInh;
    std::string CapPrm;
    std::string CapEff;
    std::string CapBnd;
    std::string Seccomp;
    std::string Cpus_allowed;
    std::string Cpus_allowed_list;
    std::string Mems_allowed;
    std::string Mems_allowed_list;
    std::string voluntary_ctxt_switches;
    std::string nonvoluntary_ctxt_switches;

    /*解析一个字符串，把信息保存在对象的字段，
     *这个成员函数完成真正的解析操作*/
    void loadFromText(const std::string &text);

    /*从proc文件系统读取信息，把信息保存在对象的字段
     *这个成员函数从proc文件系统读取原始的文件内容，
     *然后调用loadFromText完成真正的解析*/
    void loadFromSys(pid_t pid) {
        loadFromText(ProcFsUtils::getProcFileContent(pid, "status"));
    }

};

/*保存"/proc/N/stat"文件的内容*/
struct TaskStatFileContent
{
    std::string pid;
    std::string tcomm;
    std::string state;
    std::string ppid;
    std::string pgrp;
    std::string sid;
    std::string tty_nr;
    std::string tty_pgrp;
    std::string flags;
    std::string min_flt;
    std::string cmin_flt;
    std::string maj_flt;
    std::string cmaj_flt;
    std::string utime;
    std::string stime;
    std::string cutime;
    std::string cstime;
    std::string priority;
    std::string nice;
    std::string num_threads;
    std::string it_real_value;
    std::string start_time;
    std::string vsize;
    std::string rss;
    std::string rsslim;
    std::string start_code;
    std::string end_code;
    std::string start_stack;
    std::string esp;
    std::string eip;
    std::string pending;
    std::string blocked;
    std::string sigign;
    std::string sigcatch;
    std::string wchan;
    std::string place_holder_0;
    std::string place_holder_1;
    std::string exit_signal;
    std::string task_cpu;
    std::string rt_priority;
    std::string policy;
    std::string blkio_ticks;
    std::string gtime;
    std::string cgtime;
    std::string start_data;
    std::string end_data;
    std::string start_brk;
    std::string arg_start;
    std::string arg_end;
    std::string env_start;
    std::string env_end;
    std::string exit_code;

    void loadFromText(const std::string &text);

    void loadFromSys(pid_t pid) {
        loadFromText(ProcFsUtils::getProcFileContent(pid, "stat"));
    }

};

struct TaskStatmFileContent
{
    std::string size;
    std::string resident;
    std::string shared;
    std::string trs;
    std::string lrs;
    std::string drs;
    std::string dt;

    void loadFromText(const std::string &text);

    void loadFromSys(pid_t pid) {
        loadFromText(ProcFsUtils::getProcFileContent(pid, "statm"));
    }
};

struct TaskCmdlineFileContent
{
    std::string cmdline;

    void loadFromSys(pid_t pid) {
        cmdline = ProcFsUtils::getProcFileContent(pid, "cmdline");
    }
};

struct TaskFileContent
{
    TaskStatusFileContent   status;
    TaskStatFileContent     stat;
    TaskStatmFileContent    statm;
    TaskCmdlineFileContent  cmdline;

    void loadFromSys(pid_t pid) {
        status.loadFromSys(pid);
        stat.loadFromSys(pid);
        statm.loadFromSys(pid);
        cmdline.loadFromSys(pid);
    }
};

#endif // PROC_H

